package cn.skyquant.quant4j.service.boot.model.strategy;

import cn.skyquant.quant4j.api.dto.ResultDTO;
import cn.skyquant.quant4j.api.strategy.StrategyTestService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Optional;

@Service
public class StrategyTestServiceImpl implements StrategyTestService {
    @Resource
    StrategyRepository strategyRepository;
    @Resource
    StrategyTestRepository strategyTestRepository;
    @Resource
    StrategyTestDailyRepository strategyTestDailyRepository;
    @Resource
    StrategyTestStatisticsRepository strategyTestStatisticsRepository;
    @Resource
    StrategyTestOpenRepository strategyTestOpenRepository;
    @Resource
    StrategyTestCloseRepository strategyTestCloseRepository;

    @Transactional
    @Override
    public ResultDTO<Integer> start(
            String strategyName,
            String version,
            String name,
            String userName,
            long beginDate,
            String paramstr,
            double initMoney) {
        if (paramstr == null
                || strategyName == null
                || initMoney == 0
                || beginDate == 0) {
            return ResultDTO.error1;
        }
        StrategyTest st = new StrategyTest();
        st.strategyName = strategyName;
        st.version = version;
        st.userName = userName;
        st.name = name;
        st.paramstr = paramstr;
        st.initMoney = initMoney;
        st.endMoney = initMoney;
        st.isEnd = false;
        st.beginDate = new Date(beginDate);
        st.endDate = st.beginDate;
        st.startTime = new Date();
        st.endTime = st.startTime;
        StrategyTest db = strategyTestRepository.save(st);
        return ResultDTO.success(db.id);
    }

    @Transactional
    @Override
    public ResultDTO<Void> updateDaily(int id, long thedate, double balance, double equity, double open, double close, double high, double low) {
        Optional<StrategyTest> strategyTestOptional = strategyTestRepository.findById(id);
        if (strategyTestOptional.isPresent()) {
            Date date = new Date(thedate);
            StrategyTest strategyTest = strategyTestOptional.get();
            strategyTest.endDate = date;
            strategyTest.endMoney = equity;
            strategyTest.endTime = new Date();

            StrategyTestDaily daily = new StrategyTestDaily();
            daily.balance = balance;
            daily.equity = equity;
            daily.open = open;
            daily.close = close;
            daily.high = high;
            daily.low = low;
            daily.test = strategyTest;
            daily.thedate = date;
            strategyTestDailyRepository.save(daily);
            return ResultDTO.success;
        }
        return ResultDTO.error2;
    }

    @Transactional
    @Override
    public ResultDTO<Void> addOpen(int id, long thedate, String symbol, double openPrice, double amount, String action, Double sl, Double tp) {
        Optional<StrategyTest> strategyTestOptional = strategyTestRepository.findById(id);
        if (strategyTestOptional.isPresent()) {

            StrategyTestOpen open = new StrategyTestOpen();
            open.test = strategyTestOptional.get();
            open.amount = amount;
            open.symbol = symbol;
            open.openPrice = openPrice;
            open.amount = amount;
            open.action = action;
            open.sl = sl;
            open.tp = tp;
            open.thedate = new Date(thedate);
            strategyTestOpenRepository.save(open);
            return ResultDTO.success;
        }
        return ResultDTO.error2;
    }

    @Transactional
    @Override
    public ResultDTO<Void> addClose(int id, long thedate, String symbol, double avgPrice, double closePrice, double amount, String action, double profit,Double commission) {
        Optional<StrategyTest> strategyTestOptional = strategyTestRepository.findById(id);
        if (strategyTestOptional.isPresent()) {
            StrategyTestClose close = new StrategyTestClose();
            close.test = strategyTestOptional.get();
            close.amount = amount;
            close.symbol = symbol;
            close.avgPrice = avgPrice;
            close.closePrice = closePrice;
            close.amount = amount;
            close.action = action;
            close.profit = profit;
            close.commission = commission;
            close.thedate = new Date(thedate);
            strategyTestCloseRepository.save(close);
            return ResultDTO.success;
        }
        return ResultDTO.error2;
    }

    @Transactional
    @Override
    public ResultDTO<Void> addStatistics(int id, long beginTime, long endTime, double beginMoney, double endMoney, int tradeLevel,double profit, double amount,int distance) {
        Optional<StrategyTest> strategyTestOptional = strategyTestRepository.findById(id);
        if (strategyTestOptional.isPresent()) {
            StrategyTestStatistics statistics = new StrategyTestStatistics();
            statistics.test = strategyTestOptional.get();
            statistics.beginTime = new Date(beginTime);
            statistics.endTime = new Date(endTime);
            statistics.beginMoney = beginMoney;
            statistics.endMoney = endMoney;
            statistics.tradeLevel = tradeLevel;
            statistics.profit = profit;
            statistics.amount = amount;
            statistics.distance = distance;
            strategyTestStatisticsRepository.save(statistics);
            return ResultDTO.success;
        }
        return ResultDTO.error2;
    }


    @Transactional
    @Override
    public ResultDTO<Void> end(int id, long thedate, double equity) {
        Optional<StrategyTest> strategyTestOptional = strategyTestRepository.findById(id);
        if (strategyTestOptional.isPresent()) {
            StrategyTest strategyTest = strategyTestOptional.get();
            strategyTest.endDate = new Date(thedate);
            strategyTest.endMoney = equity;
            strategyTest.endTime = new Date();
            strategyTest.isEnd = true;
            return ResultDTO.success;
        }
        return ResultDTO.error2;
    }

    @Transactional
    @Override
    public ResultDTO<Void> delete(int id) {
        strategyTestStatisticsRepository.deleteByTestId(id);
        strategyTestOpenRepository.deleteByTestId(id);
        strategyTestCloseRepository.deleteByTestId(id);
        strategyTestDailyRepository.deleteByTestId(id);
        strategyTestRepository.deleteById(id);
        return ResultDTO.success;
    }
}
